#include "ubvm_quadrilateral.h"
#include "xParameterPack.h"
#include "vmLibrary.h"
#include "DIVA_Manager.h"

int ubvm_quadrilateral::_UNIQUE_INT = 0 ;
void create_quadrilateral(float* x1, float* y1, float* x2, float* y2, float* x3, float* y3, float* x4, float* y4, float* z, float* depth,Ogre::ManualObject* manual);
ubvm_quadrilateral::ubvm_quadrilateral(xParameterPack xpp)
	:DIVA_VM(xpp)
{
	int radius_port = vmLibrary::instance().get_vm_default_input_parameters().size();
	_vm_x1 = xpp.paras[radius_port].val_float_ptr; // set up the private attributes
	_vm_y1 = xpp.paras[radius_port+1].val_float_ptr ;
	_vm_x2 = xpp.paras[radius_port+2].val_float_ptr ;
	_vm_y2 = xpp.paras[radius_port+3].val_float_ptr ;
	_vm_x3 = xpp.paras[radius_port+4].val_float_ptr ;
	_vm_y3 = xpp.paras[radius_port+5].val_float_ptr ;
	_vm_x4 = xpp.paras[radius_port+6].val_float_ptr ;
	_vm_y4 = xpp.paras[radius_port+7].val_float_ptr ;
	_vm_z = xpp.paras[radius_port+8].val_float_ptr ;
	_vm_depth = xpp.paras[radius_port+9].val_float_ptr ;

	this->disableVMDraggeed();
	init_default_parameters();
}


ubvm_quadrilateral::~ubvm_quadrilateral()
{
}

void ubvm_quadrilateral::load_3Dresources()
{
	const int COLOR_MODULATE_PARAM_INDEX = 1 ;
	_mgr = DIVA_Manager::getInstance()->getSceneManager();

	_manual_name = "polygon"+ Ogre::StringConverter::toString(_UNIQUE_INT) ;
	_manual = _mgr->createManualObject(_manual_name);

	create_quadrilateral(_vm_x1,_vm_y1,_vm_x2,_vm_y2,_vm_x3,_vm_y3,_vm_x4,_vm_y4,_vm_z,_vm_depth,_manual);


	// convert it to mesh, because we want to change the color 
	_meshptr = _manual->convertToMesh("quadrilateralshape"+ Ogre::StringConverter::toString(_UNIQUE_INT) );
	_mesh_name = "quadrilateralshape"+ Ogre::StringConverter::toString(_UNIQUE_INT) ;
	_UNIQUE_INT ++ ;

	_ent = _mgr->createEntity(getNewUniqueName(), _meshptr->getName());
	_SceneNode->attachObject(_ent);
}

void ubvm_quadrilateral::reg_event_entity()
{

	// register the relation of the entity and vm in diva manager
	// When this entity is clicked, mouse/keyboard VM will be passed to this VM
	// By default it can be only one entity representing this VM
	VL_regBoundingBox(_ent);

}

void ubvm_quadrilateral::set_default_values()
{
	_vm_rx_val = 0;
	_vm_ry_val = 0;
	_vm_rz_val = 0;

	Ogre::Vector3 sz = _ent->getBoundingBox().getSize();
	_vm_init_sizex = sz.x ;
	_vm_init_sizey = sz.y ;
	_vm_init_sizez = sz.z ;

	_vm_sizex_val = sz.x ;
	_vm_sizey_val = sz.y ;
	_vm_sizez_val = sz.z ;

	_vm_sizexscale_val = 1.0 ;
	_vm_sizeyscale_val = 1.0 ;
	_vm_sizezscale_val = 1.0 ;

	_vm_r_val = 0.2;
	_vm_g_val = 0.2;
	_vm_b_val = 0.2;
	_vm_transparency_val = 1.0 ;

	_vm_yaw_val = 0 ;
	_vm_pitch_val = 0 ;
	_vm_roll_val = 0 ;
}

void ubvm_quadrilateral::init_private_attrs_started()
{
	/// do nothing when private attribute initialization starting
}

void ubvm_quadrilateral::init_private_attrs_ended()
{
	
}

void ubvm_quadrilateral::init_clickmsg()
{
	if (_prohibit_defaults[SKIP_CLICKMSG] == true) 
		return ;

	if (_vm_clickmsg != NULL) {
		_vm_clickmsg_val = * _vm_clickmsg ;
		string result = replace_clickmsg();
		_msg = VL_createVMtext(result,"MovableText");
		_msg->setVisible(false);
		_text_scene_node = VL_createTextNode((TextPosition)_vm_clickmsg_position);	
		_text_scene_node->setInheritScale(false);
		_text_scene_node ->attachObject(_msg);
		Ogre::Real x = (*_vm_x2 - *_vm_x1)/2 + *_vm_x1;
		Ogre::Real y = (*_vm_y1 - *_vm_y3)/2 + *_vm_y3;
		Ogre::Vector3 pos(x,y,_text_scene_node->getPosition().z);
		_text_scene_node->setPosition(pos);
		_msg->setCharacterHeight(40);		
		_msg->setColor(Ogre::ColourValue(1.0,5.0,0.5, 1.0f)); // init the text color to be red
		_textvisible = false ;
	}
}

void ubvm_quadrilateral::VMValueUpdated()
{
	int radius_port = vmLibrary::instance().get_vm_default_input_parameters().size();
	if (_para_onoff[radius_port]   || _para_onoff[radius_port+1] || 
		_para_onoff[radius_port+2] || _para_onoff[radius_port+3] ||
		_para_onoff[radius_port+4] || _para_onoff[radius_port+5] ||
		_para_onoff[radius_port+6] || _para_onoff[radius_port+7] ||
		_para_onoff[radius_port+8] || _para_onoff[radius_port+9]) {

		DIVA_Manager::getInstance()->dereg_MovableObj_VM_relation(_ent,this); 
		// first, we should free the previous created resources
		_SceneNode->detachObject(_ent->getName());  // deattach 
		_mgr->destroyManualObject(_manual);
		_mgr->destroyEntity(_ent); 
		Ogre::MeshManager::getSingleton().remove(_mesh_name);

		// now, we create another new donut according to the updated values
		_manual = _mgr->createManualObject("polygon"+_UNIQUE_INT );
		_manual_name = "polygon"+_UNIQUE_INT ;
		create_quadrilateral(_vm_x1,_vm_y1,_vm_x2,_vm_y2,_vm_x3,_vm_y3,_vm_x4,_vm_y4,_vm_z,_vm_depth,_manual);
		// convert it to mesh, because we want to change the color 
		_meshptr = _manual->convertToMesh("quadrilateralshape"+_UNIQUE_INT);
		_mesh_name = "quadrilateralshape"+_UNIQUE_INT ;
		_UNIQUE_INT++ ;
		_ent = _mgr->createEntity(getNewUniqueName(), _meshptr->getName());
		_SceneNode->attachObject(_ent);
		DIVA_Manager::getInstance()->reg_MovableObj_VM_relation(_ent,this); // register the new entity and vm relation
		// if this step is not done, the dragging will
		// not working
	}
	DIVA_VM::VMValueUpdated();
}

void ubvm_quadrilateral::setBodyScale( Ogre::Vector3 scale )
{
	_SceneNode ->setScale(scale);
}

Ogre::Vector3 ubvm_quadrilateral::getOriginalBodySize()
{
	Ogre::AxisAlignedBox temp = _ent ->getBoundingBox();	
	Ogre::Vector3 size = temp.getSize(); 
	return size ;
}

Ogre::Vector3 ubvm_quadrilateral::getActualSize()
{
	return getOriginalBodySize() * _SceneNode->getScale();
}

bool ubvm_quadrilateral::isBodyScaleWrtSceneNode()
{
	return true ;
}

Ogre::Vector3 ubvm_quadrilateral::getBodyScale()
{
	return _SceneNode->getScale();
}

void create_quadrilateral( float* x1, float* y1, float* x2, float* y2, float* x3, float* y3, float* x4, float* y4, float* z, float* depth,Ogre::ManualObject* manual )
{
	manual->begin("TextureModColor", Ogre::RenderOperation::OT_TRIANGLE_LIST);
	
	unsigned point_index = 0;

	// front 
	manual->position(*x4,*y4,*depth+*z);
	manual->index(point_index++);
	manual->position(*x2,*y2,*depth+*z);
	manual->index(point_index++);
	manual->position(*x1,*y1,*depth+*z);
	manual->index(point_index++);

	manual->position(*x3,*y3,*depth+*z);
	manual->index(point_index++);
	manual->position(*x4,*y4,*depth+*z);
	manual->index(point_index++);
	manual->position(*x1,*y1,*depth+*z);
	manual->index(point_index++);

	//top
	manual->position(*x1,*y1,-(*depth/2)+*z);
	manual->index(point_index++);
	manual->position(*x1,*y1,*depth+*z);
	manual->index(point_index++);
	manual->position(*x2,*y2,-(*depth/2)+*z);
	manual->index(point_index++);

	manual->position(*x1,*y1,*depth+*z);
	manual->index(point_index++);
	manual->position(*x2,*y2,*depth+*z);
	manual->index(point_index++);
	manual->position(*x2,*y2,-(*depth/2)+*z);
	manual->index(point_index++);

	//right
	manual->position(*x2,*y2,-(*depth/2)+*z);
	manual->index(point_index++);
	manual->position(*x2,*y2,*depth+*z);
	manual->index(point_index++);
	manual->position(*x4,*y4,*depth+*z);
	manual->index(point_index++);

	manual->position(*x2,*y2,-(*depth/2)+*z);
	manual->index(point_index++);
	manual->position(*x4,*y4,*depth+*z);
	manual->index(point_index++);
	manual->position(*x4,*y4,-(*depth/2)+*z);
	manual->index(point_index++);

	//bottom
	manual->position(*x3,*y3,-(*depth/2)+*z);
	manual->index(point_index++);
	manual->position(*x4,*y4,-(*depth/2)+*z);
	manual->index(point_index++);
	manual->position(*x4,*y4,*depth+*z);
	manual->index(point_index++);

	manual->position(*x3,*y3,-(*depth/2)+*z);
	manual->index(point_index++);
	manual->position(*x4,*y4,*depth+*z);
	manual->index(point_index++);
	manual->position(*x3,*y3,*depth+*z);
	manual->index(point_index++);

	//left
	manual->position(*x1,*y1,*depth+*z);
	manual->index(point_index++);
	manual->position(*x1,*y1,-(*depth/2)+*z);
	manual->index(point_index++);
	manual->position(*x3,*y3,-(*depth/2)+*z);
	manual->index(point_index++);

	manual->position(*x1,*y1,*depth+*z);
	manual->index(point_index++);
	manual->position(*x3,*y3,-(*depth/2)+*z);
	manual->index(point_index++);
	manual->position(*x3,*y3,*depth+*z);
	manual->index(point_index++);

	// back
	manual->position(*x1,*y1,-(*depth/2)+*z);
	manual->index(point_index++);
	manual->position(*x2,*y2,-(*depth/2)+*z);
	manual->index(point_index++);
	manual->position(*x4,*y4,-(*depth/2)+*z);
	manual->index(point_index++);

	manual->position(*x1,*y1,-(*depth/2)+*z);
	manual->index(point_index++);
	manual->position(*x4,*y4,-(*depth/2)+*z);
	manual->index(point_index++);
	manual->position(*x3,*y3,-(*depth/2)+*z);
	manual->index(point_index++);

	manual->end();
}
